﻿using Serilog;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting.Json;
using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.File;
using Serilog.Sinks.SystemConsole.Themes;
using System;
using System.Threading;

namespace Sustainalytics.EsgRatings.BusinessLogic
{
    public sealed class CompanyReportSerilog
    {
        public static Lazy<CompanyReportSerilog> _lazyLog = new Lazy<CompanyReportSerilog>(InitLog, LazyThreadSafetyMode.ExecutionAndPublication);
        private readonly ILogger _logger;


        public static CompanyReportSerilog Log
        {
            get
            {
                return _lazyLog.Value;
            }
        }

        public void Ping()
        {
            var eventId = 1;
            _logger.Debug("Ping {eventId}", eventId);
        }

        public static CompanyReportSerilog InitLog()
        {
            var log = new CompanyReportSerilog();
            return log;

        }

        public CompanyReportSerilog()
        {
            var loggerConfig = new LoggerConfiguration()
                  .MinimumLevel.Debug()
                  .WriteTo.Console(theme: SystemConsoleTheme.Literate)
                  .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200")) // for the docker-compose implementation
                  {
                      IndexFormat = "testcompanyreport-{0:yyyy.MM.dd}",
                      AutoRegisterTemplate = true,
                      //BufferBaseFilename = "./buffer",
                      RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
                      FailureCallback = e => Console.WriteLine("Unable to submit event " + e.MessageTemplate),
                      EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog |
                                         EmitEventFailureHandling.WriteToFailureSink |
                                         EmitEventFailureHandling.RaiseCallback,
                      FailureSink = new FileSink("../failuresCompanyReport.txt", new JsonFormatter(), null)
                  });
            _logger = loggerConfig.CreateLogger();

            SelfLog.Enable(Console.Error);
        }

        public void Exception(Exception ex)
        {
            if (ex != null)
                this.Exception(ex.GetType().ToString(), ex.Message, ex.ToString());
        }


        public void Exception(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            var eventId = 2;
            if (_logger.IsEnabled(LogEventLevel.Error))
                _logger.Error("Exception {eventId}, {exceptionType}, {exceptionMessage}, {exceptionInformation}", eventId, exceptionType, exceptionMessage, exceptionInformation);

        }

        public void Test(string controllerName, string httpMethod, int statusCode, string reasonPhrase)
        {
            var eventId = 3;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("Test {eventId}, {conrollerName}, {htpMehod}, {statusCode}, {reasonPhrase}", eventId, controllerName, httpMethod, statusCode, reasonPhrase);
            }
        }


        public void InOutEvent(string controllerName, string httpMethod, int statusCode, string reasonPhrase)
        {
            var eventId = 4;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("InOutEvent {eventId}, {conrollerName}, {htpMehod}, {statusCode}, {reasonPhrase}", eventId, controllerName, httpMethod, statusCode, reasonPhrase);
            }
        }

        public void ArgumentsEvent(string key, string value)
        {
            var eventId = 5;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("ArgumensEvent {eventId}, {key}, {value}", eventId, key, value);
            }
        }

        public void OuptputEvent(string outputValue)
        {
            var eventId = 6;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("OuptputEvent {eventId}, {outputValue}", eventId, outputValue);
            }
        }

        public void MongoEvent(string className, string dbName, string collectionName, string opName, string args, string result)
        {
            var eventId = 7;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("MongoEvent {eventId}, {className}, {dbName}, {collectionName}, {opName}, {args}, {result}", eventId, className, dbName, collectionName, opName, args, result);
            }
        }

        public void UploadFiles(string filename, string type, Guid id)
        {
            var eventId = 8;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("UploadFiles {eventId}, {filename}, {type}, {id}", eventId, filename, type, id);
            }
        }

        public void CustomCompanyReportStatus(string uri, string parameters, string responseCode, int bytes)
        {
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("Request custom PDF to {0}, with {1}, response: {2}, content in bytes: {3}. Parameters {4}", uri, responseCode,bytes, parameters);
            }
        }

        public void CustomCompanyReportExecution(string companyName, string companyId, string dataCollectionDuration, string pdfRenderingDuration)
        {
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("Custom PDF ESG Company report execution, Company Name: { 0}, Company Id: { 1}, collect CRDO: { 2}, Pdf rendering: { 3}",
                    companyName, companyId, dataCollectionDuration, pdfRenderingDuration);
            }
        }


        public void CustomCompanyExcelStatus(string uri, long requestDuration, long deserializationDuration, long contentSize)
        {
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("Request ESG excel file to {0}, request duration: {1}, deserialization duration: {2}, content size: {3}", 
                    uri, requestDuration, deserializationDuration, contentSize);
            }
        }

    
        public void TryUrl(string uri)
        {
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                var eventId = 303;
                if (_logger.IsEnabled(LogEventLevel.Information))
                    _logger.Information("Request url to {0}", uri);
            }
        }

        public void CustomCompanyReportNoResearchAvailable(string companyId, string matrixId)
        {
            var eventId = 304;
            { 
                if (_logger.IsEnabled(LogEventLevel.Information))
                    _logger.Information("Custom PDF ESG Company request for (CompanyId: {0}, MatrixId: {1}) found no research available", companyId,matrixId);
            }
        }


    }
}
